package com.example.studentknowledge.service;

import com.example.studentknowledge.entity.Article;
import com.example.studentknowledge.entity.Category;
import com.example.studentknowledge.entity.User;
import com.example.studentknowledge.repository.ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 文章服务类
 */
@Service
@Transactional
public class ArticleService {
    
    @Autowired
    private ArticleRepository articleRepository;
    
    @Autowired
    private PointService pointService;
    
    /**
     * 创建文章
     */
    public Article createArticle(Article article) {
        // 如果是发布状态，设置发布时间
        if (article.getStatus() == Article.Status.PUBLISHED) {
            article.setPublishedAt(LocalDateTime.now());
        }
        
        // 生成文章摘要（如果没有提供）
        if (article.getSummary() == null || article.getSummary().trim().isEmpty()) {
            article.setSummary(generateSummary(article.getContent()));
        }
        
        Article savedArticle = articleRepository.save(article);
        
        // 如果是发布状态，给作者奖励积分
        if (savedArticle.getStatus() == Article.Status.PUBLISHED) {
            pointService.rewardForArticleCreate(savedArticle.getAuthor(), savedArticle.getId());
        }
        
        return savedArticle;
    }
    
    /**
     * 更新文章
     */
    public Article updateArticle(Article article) {
        Article existingArticle = articleRepository.findById(article.getId())
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 检查是否从草稿变为发布状态
        boolean wasPublished = existingArticle.getStatus() == Article.Status.PUBLISHED;
        boolean isNowPublished = article.getStatus() == Article.Status.PUBLISHED;
        
        // 如果从非发布状态变为发布状态，设置发布时间并奖励积分
        if (!wasPublished && isNowPublished) {
            article.setPublishedAt(LocalDateTime.now());
            pointService.rewardForArticleCreate(article.getAuthor(), article.getId());
        }
        
        // 更新摘要
        if (article.getSummary() == null || article.getSummary().trim().isEmpty()) {
            article.setSummary(generateSummary(article.getContent()));
        }
        
        return articleRepository.save(article);
    }
    
    /**
     * 更新文章（带用户验证）
     */
    public Article updateArticle(Article article, User user) {
        Article existingArticle = articleRepository.findById(article.getId())
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 检查用户是否有权限更新文章
        if (!existingArticle.getAuthor().getId().equals(user.getId())) {
            throw new RuntimeException("没有权限更新此文章");
        }
        
        return updateArticle(article);
    }
    
    /**
     * 根据ID查找文章
     */
    public Optional<Article> findById(Long id) {
        return articleRepository.findById(id);
    }
    
    /**
     * 根据ID获取文章
     */
    public Article getArticleById(Long id) {
        return articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
    }
    
    /**
     * 查看文章（增加浏览量）
     */
    public Article viewArticle(Long id) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 增加浏览量
        articleRepository.incrementViewCount(id);
        article.setViewCount(article.getViewCount() + 1);
        
        return article;
    }
    
    /**
     * 删除文章
     */
    public void deleteArticle(Long id) {
        articleRepository.deleteById(id);
    }
    
    /**
     * 删除文章（带用户验证）
     */
    public void deleteArticle(Long id, User user) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 检查用户是否有权限删除文章
        if (!canDeleteArticle(article, user)) {
            throw new RuntimeException("没有权限删除此文章");
        }
        
        articleRepository.deleteById(id);
    }
    
    /**
     * 获取已发布的文章列表
     */
    public Page<Article> getPublishedArticles(Pageable pageable) {
        return articleRepository.findByStatus(Article.Status.PUBLISHED, pageable);
    }
    
    /**
     * 获取所有文章列表（管理员用）
     */
    public Page<Article> getAllArticles(Pageable pageable) {
        return articleRepository.findAll(pageable);
    }
    
    /**
     * 根据作者获取文章
     */
    public Page<Article> getArticlesByAuthor(User author, Pageable pageable) {
        return articleRepository.findByAuthor(author, pageable);
    }
    
    /**
     * 根据分类获取文章
     */
    public Page<Article> getArticlesByCategory(Category category, Pageable pageable) {
        return articleRepository.findByCategoryAndStatus(category, Article.Status.PUBLISHED, pageable);
    }
    
    /**
     * 根据分类ID获取文章
     */
    public Page<Article> getArticlesByCategory(Long categoryId, Pageable pageable) {
        Category category = new Category();
        category.setId(categoryId);
        return articleRepository.findByCategoryAndStatus(category, Article.Status.PUBLISHED, pageable);
    }
    
    /**
     * 搜索文章
     */
    public Page<Article> searchArticles(String keyword, Pageable pageable) {
        return articleRepository.findByTitleOrContentContainingAndStatus(keyword, Article.Status.PUBLISHED, pageable);
    }
    
    /**
     * 获取热门文章
     */
    public List<Article> getPopularArticles(int limit) {
        return articleRepository.findPopularArticles(Pageable.ofSize(limit));
    }
    
    /**
     * 获取最新文章
     */
    public List<Article> getLatestArticles(int limit) {
        return articleRepository.findLatestArticles(Pageable.ofSize(limit));
    }
    
    /**
     * 获取推荐文章
     */
    public List<Article> getRecommendedArticles(int limit) {
        return articleRepository.findRecommendedArticles(Pageable.ofSize(limit));
    }
    
    /**
     * 点赞文章
     */
    public void likeArticle(Long articleId, User user) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 增加点赞数
        articleRepository.incrementLikeCount(articleId);
        
        // 给点赞用户奖励积分
        pointService.rewardForLike(user, articleId);
    }
    
    /**
     * 取消点赞文章
     */
    public void unlikeArticle(Long articleId) {
        articleRepository.decrementLikeCount(articleId);
    }
    
    /**
     * 切换点赞状态（简化实现，总是返回true表示点赞成功）
     * 注意：这是一个简化实现，实际项目中应该跟踪用户的点赞状态
     */
    public boolean toggleLike(Long articleId, User user) {
        Article article = articleRepository.findById(articleId)
                .orElseThrow(() -> new RuntimeException("文章不存在"));
        
        // 简化实现：直接增加点赞数
        articleRepository.incrementLikeCount(articleId);
        pointService.rewardForLike(user, articleId);
        
        return true; // 返回true表示点赞成功
    }
    
    /**
     * 更新文章评论数
     */
    public void updateCommentCount(Long articleId) {
        articleRepository.updateCommentCount(articleId);
    }
    
    /**
     * 更新文章收藏数
     */
    public void updateFavoriteCount(Long articleId) {
        articleRepository.updateFavoriteCount(articleId);
    }
    
    /**
     * 增加文章浏览量
     */
    public void incrementViewCount(Long articleId) {
        articleRepository.incrementViewCount(articleId);
    }
    
    /**
     * 根据时间范围获取文章
     */
    public List<Article> getArticlesByDateRange(LocalDateTime startDate, LocalDateTime endDate) {
        return articleRepository.findByPublishedAtBetween(startDate, endDate);
    }
    
    /**
     * 根据时间范围获取文章（分页）
     */
    public Page<Article> getArticlesByDateRange(LocalDateTime startDate, LocalDateTime endDate, Pageable pageable) {
        return articleRepository.findByPublishedAtBetween(startDate, endDate, pageable);
    }
    
    /**
     * 统计已发布文章总数
     */
    public Long countPublishedArticles() {
        return articleRepository.countPublishedArticles();
    }
    
    /**
     * 统计用户发布的文章数
     */
    public Long countUserArticles(User author) {
        return articleRepository.countByAuthorAndStatus(author);
    }
    
    /**
     * 统计分类下的文章数
     */
    public Long countCategoryArticles(Category category) {
        return articleRepository.countByCategoryAndStatus(category);
    }
    
    /**
     * 生成文章摘要
     */
    private String generateSummary(String content) {
        if (content == null || content.trim().isEmpty()) {
            return "";
        }
        
        // 移除HTML标签
        String plainText = content.replaceAll("<[^>]*>", "");
        
        // 截取前200个字符作为摘要
        if (plainText.length() <= 200) {
            return plainText;
        }
        
        return plainText.substring(0, 200) + "...";
    }
    
    /**
     * 检查用户是否有权限编辑文章
     */
    public boolean canEditArticle(Article article, User user) {
        // 管理员可以编辑所有文章
        if (user.getRole() == User.Role.ADMIN) {
            return true;
        }
        
        // 作者可以编辑自己的文章
        return article.getAuthor().getId().equals(user.getId());
    }
    
    /**
     * 检查用户是否有权限删除文章
     */
    public boolean canDeleteArticle(Article article, User user) {
        return canEditArticle(article, user);
    }
    
    /**
     * 检查用户是否有权限编辑文章
     */
    public boolean canUserEditArticle(User user, Long articleId) {
        Optional<Article> articleOpt = articleRepository.findById(articleId);
        return articleOpt.isPresent() && articleOpt.get().getAuthor().getId().equals(user.getId());
    }
    
    /**
     * 检查用户是否有权限删除文章
     */
    public boolean canUserDeleteArticle(User user, Long articleId) {
        return canUserEditArticle(user, articleId); // 编辑和删除权限相同
    }
    
    /**
     * 获取用户的文章列表（分页）
     */
    public Page<Article> getUserArticles(User user, int page, int size, String status, Long categoryId, String keyword) {
        Pageable pageable = PageRequest.of(page, size);
        
        if (status != null && !status.isEmpty()) {
            Article.Status articleStatus = Article.Status.valueOf(status);
            if (categoryId != null && keyword != null && !keyword.isEmpty()) {
                return articleRepository.findByAuthorAndStatusAndCategory_IdAndTitleContainingIgnoreCase(
                    user, articleStatus, categoryId, keyword, pageable);
            } else if (categoryId != null) {
                return articleRepository.findByAuthorAndStatusAndCategory_Id(user, articleStatus, categoryId, pageable);
            } else if (keyword != null && !keyword.isEmpty()) {
                return articleRepository.findByAuthorAndStatusAndTitleContainingIgnoreCase(
                    user, articleStatus, keyword, pageable);
            } else {
                return articleRepository.findByAuthorAndStatus(user, articleStatus, pageable);
            }
        } else {
            if (categoryId != null && keyword != null && !keyword.isEmpty()) {
                return articleRepository.findByAuthorAndCategory_IdAndTitleContainingIgnoreCase(
                    user, categoryId, keyword, pageable);
            } else if (categoryId != null) {
                return articleRepository.findByAuthorAndCategory_Id(user, categoryId, pageable);
            } else if (keyword != null && !keyword.isEmpty()) {
                return articleRepository.findByAuthorAndTitleContainingIgnoreCase(user, keyword, pageable);
            } else {
                return articleRepository.findByAuthor(user, pageable);
            }
        }
    }
}